"""
视频输入管理模块
支持多路视频流接入，包括RTSP、WebRTC和本地文件
"""

import cv2
import asyncio
import threading
import time
from typing import Dict, List, Optional, Callable, Any
from dataclasses import dataclass
from enum import Enum
from queue import Queue, Empty
import numpy as np
from pathlib import Path

from ..core import config, video_logger


class StreamType(Enum):
    """视频流类型"""
    LOCAL_FILE = "local_file"
    RTSP = "rtsp"
    WEBRTC = "webrtc"
    USB_CAMERA = "usb_camera"
    IP_CAMERA = "ip_camera"


class StreamStatus(Enum):
    """视频流状态"""
    STOPPED = "stopped"
    STARTING = "starting"
    RUNNING = "running"
    ERROR = "error"
    PAUSED = "paused"


@dataclass
class FrameData:
    """帧数据结构"""
    stream_id: str
    frame: np.ndarray
    timestamp: float
    frame_number: int
    fps: float
    width: int
    height: int


@dataclass
class StreamConfig:
    """视频流配置"""
    stream_id: str
    stream_type: StreamType
    source: str  # 文件路径、RTSP URL等
    fps: Optional[int] = None
    resolution: Optional[tuple] = None
    buffer_size: int = 100
    auto_reconnect: bool = True
    reconnect_interval: int = 5


class VideoStream:
    """单个视频流处理类"""
    
    def __init__(self, stream_config: StreamConfig, frame_callback: Callable[[FrameData], None]):
        self.config = stream_config
        self.frame_callback = frame_callback
        self.status = StreamStatus.STOPPED
        self.cap: Optional[cv2.VideoCapture] = None
        self.thread: Optional[threading.Thread] = None
        self.stop_event = threading.Event()
        self.frame_queue = Queue(maxsize=stream_config.buffer_size)
        self.frame_count = 0
        self.last_frame_time = 0
        self.actual_fps = 0
        
        video_logger.info(f"初始化视频流: {stream_config.stream_id}")
    
    def start(self) -> bool:
        """启动视频流"""
        if self.status == StreamStatus.RUNNING:
            video_logger.warning(f"视频流 {self.config.stream_id} 已在运行")
            return True
        
        try:
            self.status = StreamStatus.STARTING
            video_logger.info(f"启动视频流: {self.config.stream_id}")
            
            # 初始化视频捕获
            if not self._init_capture():
                return False
            
            # 启动处理线程
            self.stop_event.clear()
            self.thread = threading.Thread(target=self._capture_loop, daemon=True)
            self.thread.start()
            
            self.status = StreamStatus.RUNNING
            video_logger.info(f"视频流启动成功: {self.config.stream_id}")
            return True
            
        except Exception as e:
            video_logger.error(f"启动视频流失败 {self.config.stream_id}: {e}")
            self.status = StreamStatus.ERROR
            return False
    
    def stop(self):
        """停止视频流"""
        video_logger.info(f"停止视频流: {self.config.stream_id}")
        self.stop_event.set()
        
        if self.thread and self.thread.is_alive():
            self.thread.join(timeout=5)
        
        if self.cap:
            self.cap.release()
            self.cap = None
        
        self.status = StreamStatus.STOPPED
        video_logger.info(f"视频流已停止: {self.config.stream_id}")
    
    def pause(self):
        """暂停视频流"""
        if self.status == StreamStatus.RUNNING:
            self.status = StreamStatus.PAUSED
            video_logger.info(f"视频流已暂停: {self.config.stream_id}")
    
    def resume(self):
        """恢复视频流"""
        if self.status == StreamStatus.PAUSED:
            self.status = StreamStatus.RUNNING
            video_logger.info(f"视频流已恢复: {self.config.stream_id}")
    
    def _init_capture(self) -> bool:
        """初始化视频捕获"""
        try:
            if self.config.stream_type == StreamType.LOCAL_FILE:
                if not Path(self.config.source).exists():
                    video_logger.error(f"视频文件不存在: {self.config.source}")
                    return False
                self.cap = cv2.VideoCapture(self.config.source)
            
            elif self.config.stream_type == StreamType.RTSP:
                self.cap = cv2.VideoCapture(self.config.source)
                self.cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)  # 减少缓冲延迟
            
            elif self.config.stream_type == StreamType.USB_CAMERA:
                camera_id = int(self.config.source) if self.config.source.isdigit() else 0
                self.cap = cv2.VideoCapture(camera_id)
            
            else:
                video_logger.error(f"不支持的流类型: {self.config.stream_type}")
                return False
            
            if not self.cap or not self.cap.isOpened():
                video_logger.error(f"无法打开视频源: {self.config.source}")
                return False
            
            # 设置分辨率
            if self.config.resolution:
                width, height = self.config.resolution
                self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, width)
                self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height)
            
            # 设置FPS
            if self.config.fps:
                self.cap.set(cv2.CAP_PROP_FPS, self.config.fps)
            
            # 获取实际参数
            actual_width = int(self.cap.get(cv2.CAP_PROP_FRAME_WIDTH))
            actual_height = int(self.cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
            actual_fps = self.cap.get(cv2.CAP_PROP_FPS)
            
            video_logger.info(
                f"视频流参数 {self.config.stream_id}: "
                f"{actual_width}x{actual_height}@{actual_fps}fps"
            )
            
            return True
            
        except Exception as e:
            video_logger.error(f"初始化视频捕获失败: {e}")
            return False
    
    def _capture_loop(self):
        """视频捕获循环"""
        video_logger.info(f"开始视频捕获循环: {self.config.stream_id}")
        
        frame_interval = 1.0 / config.video_input.sampling_rate if config.video_input.sampling_rate > 0 else 0
        last_sample_time = 0
        
        while not self.stop_event.is_set():
            try:
                if self.status == StreamStatus.PAUSED:
                    time.sleep(0.1)
                    continue
                
                ret, frame = self.cap.read()
                if not ret:
                    if self.config.stream_type == StreamType.LOCAL_FILE:
                        video_logger.info(f"视频文件播放完成: {self.config.stream_id}")
                        break
                    elif self.config.auto_reconnect:
                        video_logger.warning(f"视频流断开，尝试重连: {self.config.stream_id}")
                        if self._reconnect():
                            continue
                        else:
                            break
                    else:
                        video_logger.error(f"读取帧失败: {self.config.stream_id}")
                        break
                
                current_time = time.time()
                
                # 降帧采样
                if frame_interval > 0 and (current_time - last_sample_time) < frame_interval:
                    continue
                
                last_sample_time = current_time
                self.frame_count += 1
                
                # 计算实际FPS
                if self.last_frame_time > 0:
                    self.actual_fps = 1.0 / (current_time - self.last_frame_time)
                self.last_frame_time = current_time
                
                # 创建帧数据
                frame_data = FrameData(
                    stream_id=self.config.stream_id,
                    frame=frame,
                    timestamp=current_time,
                    frame_number=self.frame_count,
                    fps=self.actual_fps,
                    width=frame.shape[1],
                    height=frame.shape[0]
                )
                
                # 调用回调函数
                try:
                    self.frame_callback(frame_data)
                except Exception as e:
                    video_logger.error(f"帧回调处理失败: {e}")
                
            except Exception as e:
                video_logger.error(f"视频捕获循环异常: {e}")
                if not self.config.auto_reconnect:
                    break
                time.sleep(1)
        
        self.status = StreamStatus.STOPPED
        video_logger.info(f"视频捕获循环结束: {self.config.stream_id}")
    
    def _reconnect(self) -> bool:
        """重连视频流"""
        video_logger.info(f"尝试重连视频流: {self.config.stream_id}")
        
        if self.cap:
            self.cap.release()
        
        time.sleep(self.config.reconnect_interval)
        
        if self._init_capture():
            video_logger.info(f"视频流重连成功: {self.config.stream_id}")
            return True
        else:
            video_logger.error(f"视频流重连失败: {self.config.stream_id}")
            return False


class VideoInputManager:
    """视频输入管理器"""
    
    def __init__(self):
        self.streams: Dict[str, VideoStream] = {}
        self.frame_callbacks: List[Callable[[FrameData], None]] = []
        self.max_streams = config.video_input.max_streams
        
        video_logger.info("视频输入管理器初始化完成")
    
    def add_frame_callback(self, callback: Callable[[FrameData], None]):
        """添加帧处理回调"""
        self.frame_callbacks.append(callback)
        video_logger.info("添加帧处理回调")
    
    def remove_frame_callback(self, callback: Callable[[FrameData], None]):
        """移除帧处理回调"""
        if callback in self.frame_callbacks:
            self.frame_callbacks.remove(callback)
            video_logger.info("移除帧处理回调")
    
    def add_stream(self, stream_config: StreamConfig) -> bool:
        """添加视频流"""
        if len(self.streams) >= self.max_streams:
            video_logger.error(f"已达到最大视频流数量限制: {self.max_streams}")
            return False
        
        if stream_config.stream_id in self.streams:
            video_logger.warning(f"视频流已存在: {stream_config.stream_id}")
            return False
        
        try:
            stream = VideoStream(stream_config, self._on_frame_received)
            self.streams[stream_config.stream_id] = stream
            video_logger.info(f"添加视频流: {stream_config.stream_id}")
            return True
            
        except Exception as e:
            video_logger.error(f"添加视频流失败: {e}")
            return False
    
    def remove_stream(self, stream_id: str) -> bool:
        """移除视频流"""
        if stream_id not in self.streams:
            video_logger.warning(f"视频流不存在: {stream_id}")
            return False
        
        try:
            stream = self.streams[stream_id]
            stream.stop()
            del self.streams[stream_id]
            video_logger.info(f"移除视频流: {stream_id}")
            return True
            
        except Exception as e:
            video_logger.error(f"移除视频流失败: {e}")
            return False
    
    def start_stream(self, stream_id: str) -> bool:
        """启动视频流"""
        if stream_id not in self.streams:
            video_logger.error(f"视频流不存在: {stream_id}")
            return False
        
        return self.streams[stream_id].start()
    
    def stop_stream(self, stream_id: str) -> bool:
        """停止视频流"""
        if stream_id not in self.streams:
            video_logger.error(f"视频流不存在: {stream_id}")
            return False
        
        self.streams[stream_id].stop()
        return True
    
    def start_all_streams(self):
        """启动所有视频流"""
        video_logger.info("启动所有视频流")
        for stream_id, stream in self.streams.items():
            if stream.status == StreamStatus.STOPPED:
                stream.start()
    
    def stop_all_streams(self):
        """停止所有视频流"""
        video_logger.info("停止所有视频流")
        for stream in self.streams.values():
            stream.stop()
    
    def get_stream_status(self, stream_id: str) -> Optional[StreamStatus]:
        """获取视频流状态"""
        if stream_id in self.streams:
            return self.streams[stream_id].status
        return None
    
    def get_all_stream_status(self) -> Dict[str, StreamStatus]:
        """获取所有视频流状态"""
        return {stream_id: stream.status for stream_id, stream in self.streams.items()}
    
    def _on_frame_received(self, frame_data: FrameData):
        """帧接收回调"""
        for callback in self.frame_callbacks:
            try:
                callback(frame_data)
            except Exception as e:
                video_logger.error(f"帧回调处理失败: {e}")
    
    def cleanup(self):
        """清理资源"""
        video_logger.info("清理视频输入管理器资源")
        self.stop_all_streams()
        self.streams.clear()
        self.frame_callbacks.clear()
